from flask import Flask, render_template, jsonify, request
import serial
import sqlite3
import time
import threading
import json
from datetime import datetime
from ai_detection import AIFaultDetector

app = Flask(__name__)
ser = None
latest_data = {}

# 初始化AI故障检测器
detector = AIFaultDetector()

# 初始化数据库
def init_db():
    conn = sqlite3.connect('plc_data.db')
    cursor = conn.cursor()
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS plc_data (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            timestamp TEXT,
            sensor1 REAL,
            sensor2 REAL,
            sensor3 REAL,
            sensor4 REAL,
            relay1 INTEGER,
            relay2 INTEGER,
            relay3 INTEGER,
            relay4 INTEGER,
            fault_status INTEGER
        )
    ''')
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS configurations (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            name TEXT UNIQUE,
            value TEXT
        )
    ''')
    conn.commit()
    conn.close()

# 保存配置
def save_config(name, value):
    conn = sqlite3.connect('plc_data.db')
    cursor = conn.cursor()
    cursor.execute("INSERT OR REPLACE INTO configurations (name, value) VALUES (?, ?)", (name, value))
    conn.commit()
    conn.close()

# 读取配置
def get_config(name, default=None):
    conn = sqlite3.connect('plc_data.db')
    cursor = conn.cursor()
    cursor.execute("SELECT value FROM configurations WHERE name = ?", (name,))
    result = cursor.fetchone()
    conn.close()
    if result:
        return result[0]
    return default

# 数据接收线程
def serial_thread():
    global ser, latest_data
    port = get_config('serial_port', 'COM3')
    baud_rate = int(get_config('baud_rate', '9600'))
    
    while True:
        try:
            if ser is None or not ser.isOpen():
                try:
                    ser = serial.Serial(port, baud_rate, timeout=1)
                    print(f"Connected to {port} at {baud_rate} baud")
                except Exception as e:
                    print(f"Error opening serial port: {e}")
                    time.sleep(5)
                    continue
            
            if ser.in_waiting > 0:
                line = ser.readline().decode('utf-8').strip()
                if line:
                    try:
                        # 假设Arduino发送的数据格式为: sensor1,sensor2,sensor3,sensor4,relay1,relay2,relay3,relay4,fault_status
                        data = line.split(',')
                        if len(data) == 9:
                            timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                            
                            # 更新最新数据
                            latest_data = {
                                'timestamp': timestamp,
                                'sensor1': float(data[0]),
                                'sensor2': float(data[1]),
                                'sensor3': float(data[2]),
                                'sensor4': float(data[3]),
                                'relay1': int(data[4]),
                                'relay2': int(data[5]),
                                'relay3': int(data[6]),
                                'relay4': int(data[7]),
                                'fault_status': int(data[8])
                            }
                            
                            # 保存到数据库
                            conn = sqlite3.connect('plc_data.db')
                            cursor = conn.cursor()
                            cursor.execute(
                                '''INSERT INTO plc_data 
                                (timestamp, sensor1, sensor2, sensor3, sensor4, relay1, relay2, relay3, relay4, fault_status) 
                                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''',
                                (timestamp, latest_data['sensor1'], latest_data['sensor2'], latest_data['sensor3'], 
                                 latest_data['sensor4'], latest_data['relay1'], latest_data['relay2'], 
                                 latest_data['relay3'], latest_data['relay4'], latest_data['fault_status'])
                            )
                            conn.commit()
                            conn.close()
                            
                            print(f"Data received: {latest_data}")
                    except Exception as e:
                        print(f"Error parsing data: {e}")
        except Exception as e:
            print(f"Serial thread error: {e}")
            if ser is not None:
                ser.close()
                ser = None
            time.sleep(5)
        
        time.sleep(0.1)

# 发送命令到Arduino
def send_command(command):
    global ser
    try:
        if ser is not None and ser.isOpen():
            ser.write((command + '\n').encode())
            return True
        return False
    except Exception as e:
        print(f"Error sending command: {e}")
        return False

# API - 获取最新数据
@app.route('/api/latest_data')
def api_latest_data():
    global latest_data
    return jsonify(latest_data)

# API - 获取历史数据
@app.route('/api/history_data')
def api_history_data():
    start_time = request.args.get('start_time', '')
    end_time = request.args.get('end_time', '')
    limit = request.args.get('limit', 100, type=int)
    
    conn = sqlite3.connect('plc_data.db')
    cursor = conn.cursor()
    
    if start_time and end_time:
        cursor.execute(
            '''SELECT timestamp, sensor1, sensor2, sensor3, sensor4, relay1, relay2, relay3, relay4, fault_status 
            FROM plc_data WHERE timestamp BETWEEN ? AND ? ORDER BY timestamp DESC LIMIT ?''',
            (start_time, end_time, limit)
        )
    else:
        cursor.execute(
            '''SELECT timestamp, sensor1, sensor2, sensor3, sensor4, relay1, relay2, relay3, relay4, fault_status 
            FROM plc_data ORDER BY timestamp DESC LIMIT ?''',
            (limit,)
        )
    
    data = cursor.fetchall()
    conn.close()
    
    result = []
    for row in data:
        result.append({
            'timestamp': row[0],
            'sensor1': row[1],
            'sensor2': row[2],
            'sensor3': row[3],
            'sensor4': row[4],
            'relay1': row[5],
            'relay2': row[6],
            'relay3': row[7],
            'relay4': row[8],
            'fault_status': row[9]
        })
    
    return jsonify(result)

# API - 控制继电器
@app.route('/api/control_relay', methods=['POST'])
def api_control_relay():
    data = request.json
    relay_id = data.get('relay_id')
    state = data.get('state')
    
    if relay_id is None or state is None:
        return jsonify({'success': False, 'message': 'Missing relay_id or state'})
    
    if 1 <= relay_id <= 4 and state in [0, 1]:
        command = f"RELAY,{relay_id},{state}"
        success = send_command(command)
        return jsonify({'success': success, 'message': 'Command sent' if success else 'Failed to send command'})
    else:
        return jsonify({'success': False, 'message': 'Invalid relay_id or state'})

# API - 设置配置
@app.route('/api/set_config', methods=['POST'])
def api_set_config():
    data = request.json
    name = data.get('name')
    value = data.get('value')
    
    if name and value:
        save_config(name, value)
        return jsonify({'success': True, 'message': 'Configuration saved'})
    else:
        return jsonify({'success': False, 'message': 'Missing name or value'})

# API - 获取配置
@app.route('/api/get_config')
def api_get_config():
    name = request.args.get('name')
    
    if name:
        value = get_config(name)
        return jsonify({'success': True, 'value': value})
    else:
        conn = sqlite3.connect('plc_data.db')
        cursor = conn.cursor()
        cursor.execute("SELECT name, value FROM configurations")
        configs = cursor.fetchall()
        conn.close()
        
        result = {}
        for config in configs:
            result[config[0]] = config[1]
        
        return jsonify({'success': True, 'configs': result})

# 主页面
@app.route('/')
def index():
    return render_template('index.html')

# API - AI故障检测
@app.route('/api/fault_detection/latest')
def api_latest_fault():
    latest_fault = detector.get_latest_fault()
    return jsonify({'success': True, 'fault': latest_fault})

@app.route('/api/fault_detection/history')
def api_fault_history():
    limit = request.args.get('limit', 10, type=int)
    history = detector.get_fault_history(limit)
    return jsonify({'success': True, 'history': history})

@app.route('/api/fault_detection/baselines')
def api_get_baselines():
    baselines = detector.get_baselines()
    return jsonify({'success': True, 'baselines': baselines})

@app.route('/api/fault_detection/set_baseline', methods=['POST'])
def api_set_baseline():
    data = request.json
    sensor = data.get('sensor')
    mean = data.get('mean')
    std = data.get('std')
    threshold = data.get('threshold', 3.0)
    
    if not sensor or mean is None or std is None:
        return jsonify({'success': False, 'message': 'Missing required parameters'})
    
    success = detector.set_baseline(sensor, mean, std, threshold)
    return jsonify({'success': success, 'message': 'Baseline updated' if success else 'Invalid sensor'})

@app.route('/api/fault_detection/calibrate', methods=['POST'])
def api_calibrate_baseline():
    data = request.json
    duration = data.get('duration', 60)
    
    # 在后台启动校准
    threading.Thread(target=detector.calibrate_baseline, args=(duration,)).start()
    return jsonify({'success': True, 'message': f'Calibration started for {duration} seconds'})

@app.route('/api/fault_detection/trend')
def api_analyze_trend():
    sensor = request.args.get('sensor', 'sensor1')
    time_window = request.args.get('time_window', 60, type=int)
    
    trend = detector.analyze_trend(sensor, time_window)
    return jsonify({'success': True, 'trend': trend})

if __name__ == '__main__':
    init_db()
    
    # 启动AI故障检测器
    detector.start()
    
    # 启动串行通信线程
    serial_thread_obj = threading.Thread(target=serial_thread)
    serial_thread_obj.daemon = True
    serial_thread_obj.start()
    
    # 启动Flask服务
    try:
        app.run(debug=True, host='0.0.0.0', port=5000)
    finally:
        # 确保在退出时停止所有服务
        detector.stop()
        if ser is not None and ser.isOpen():
            ser.close()